package com.app.core.validator;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ResourceUtils;

import com.alibaba.fastjson.JSONObject;
import com.app.core.util.Out;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

/**
 * 
 * TODO Comment.
 * 
 * @since v#{version}
 * @author zhangxf
 * @created 2015年10月28日 上午8:05:17
 */
public class ValidatorContext implements Serializable {

    /**  */
    private static final long serialVersionUID = 1L;
    private static final String validatePath = "classpath:validate";
    private static final String validateConfigName = "config.json";

    /* 是否自动更新模式 */
    public static boolean autoUpdate;
    public static int autoUpdateSecond;
    public static Thread autoUpdateThread;
    public static long configFileUpdateTime;
    public static Map<String, Long> fileUpdateTimeCache;

    public static Map<String, ValidatorConfig> configMap;
    public static Map<String, String> defaultMsg;

    public static void init() {
        Out.i("init validator....");
        configMap = new HashMap<String, ValidatorConfig>();
        fileUpdateTimeCache = new HashMap<String, Long>();
        try {
            // URL url = ResourceUtils.getURL(validatePath);  
            String path = ValidatorContext.class.getClassLoader().getResource("").getPath() + "/validate";
            Out.i(path);
            File[] listFiles = new File(path).listFiles();
            if (listFiles == null) {
                Out.w("未初始化validate! 原因:未加载到配置文件，" + path);
                return;
            }
            for (File file : listFiles) {
                fileUpdateTimeCache.put(file.getName(), file.lastModified());
                if (file.getName().equals(validateConfigName)) {
                    initDefaultMsg(FileUtils.readFileToString(file, "utf-8"));
                    continue;
                }

                initBeanRule(null, FileUtils.readFileToString(file, "utf-8"));
                initBeanRule(file.getName().replace(".json", ""), FileUtils.readFileToString(file, "utf-8"));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        Out.i("init validator end.");

        autoUpdate();
    }

    public static void autoUpdate() {
        if (!autoUpdate)
            return;

        autoUpdateThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while (autoUpdate) {
                    try {
                        Thread.sleep(autoUpdateSecond * 1000);
                        URL url = ResourceUtils.getURL(validatePath);
                        File[] listFiles = new File(url.getFile()).listFiles();
                        for (File file : listFiles) {
                            Long lastModified = fileUpdateTimeCache.get(file.getName());
                            if (lastModified == null || file.lastModified() > lastModified) {
                                Out.i("validator config update file:" + file.getName());
                                fileUpdateTimeCache.put(file.getName(), file.lastModified());
                                if (file.getName().equals(validateConfigName)) {
                                    initDefaultMsg(FileUtils.readFileToString(file, "utf-8"));
                                    continue;
                                }

                                initBeanRule(null, FileUtils.readFileToString(file, "utf-8"));
                                initBeanRule(file.getName().replace(".json", ""), FileUtils.readFileToString(file, "utf-8"));
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        autoUpdateThread.start();
    }

    private static void initDefaultMsg(String data) {
        defaultMsg = new HashMap<String, String>();
        JSONObject jsonObject1 = JSONObject.parseObject(data).getJSONObject("defaultMsg");
        Set<String> keySet1 = jsonObject1.keySet();
        for (String key : keySet1) {
            defaultMsg.put(key, jsonObject1.getString(key));
        }
    }

    private static void initBeanRule(String filename, String data) {
        JsonObject jsonObject = new Gson().fromJson(data, JsonObject.class);
        if (jsonObject == null) {
            return;
        }
        String bean = jsonObject.get("object").getAsString();

        // 此段代码是为了做以文件名作为校验器的key---start
        if (StringUtils.isNotBlank(filename)) {
            bean = filename;
        }
        // ----end
        
        if(jsonObject.get("code") != null){
        	String code = jsonObject.get("code").getAsString();
        	bean = bean + "_" + code;
        }
        
        ValidatorConfig config = new ValidatorConfig();
        config.setObject(bean);
        jsonObject.remove("object");
        config.setJson(jsonObject.toString());
        configMap.put(bean, config);

        Map<String, Map<String, String>> rulesMap = new LinkedHashMap<String, Map<String, String>>();
        config.setRules(rulesMap);
        
        Map<String, String> namesMap = new LinkedHashMap<String, String>();
        config.setNames(namesMap);

        JsonObject rulesJsonObject = jsonObject.getAsJsonObject("rules");
        Set<Entry<String, JsonElement>> ruleskeySet = rulesJsonObject.entrySet();
        for (Entry<String, JsonElement> entry : ruleskeySet) {
            Set<Entry<String, JsonElement>> entrySet = rulesJsonObject.getAsJsonObject(entry.getKey()).entrySet();
            Map<String, String> map = new LinkedHashMap<String, String>();
            rulesMap.put(entry.getKey(), map);
            for (Entry<String, JsonElement> entry2 : entrySet) {
                if("name".equals(entry2.getKey())){
                	namesMap.put(entry.getKey(), entry2.getValue().getAsString());
                }else{
                	map.put(entry2.getKey(), entry2.getValue().getAsString());
                }
            }
        }

        JsonObject messagesJsonObject = jsonObject.getAsJsonObject("messages");
        if (messagesJsonObject == null) {
            return;
        }
        Map<String, Map<String, String>> messagesMap = new LinkedHashMap<String, Map<String, String>>();
        config.setMessages(messagesMap);

        Set<Entry<String, JsonElement>> messageskeySet = messagesJsonObject.entrySet();
        for (Entry<String, JsonElement> entry : messageskeySet) {
            Set<Entry<String, JsonElement>> entrySet = messagesJsonObject.getAsJsonObject(entry.getKey()).entrySet();
            Map<String, String> map = new LinkedHashMap<String, String>();
            messagesMap.put(entry.getKey(), map);
            for (Entry<String, JsonElement> entry2 : entrySet) {
                map.put(entry2.getKey(), entry2.getValue().getAsString());
            }
        }

        JsonObject namesJsonObject = jsonObject.getAsJsonObject("names");
        if (namesJsonObject == null) {
            return;
        }

        Set<Entry<String, JsonElement>> nameskeySet = namesJsonObject.entrySet();
        for (Entry<String, JsonElement> entry : nameskeySet) {
            namesMap.put(entry.getKey(), entry.getValue().getAsString());
        }
    }

    public static ValidatorConfig bean(Class<?> clazz) {
        return configMap.get(clazz.getName());
    }

    public void setAutoUpdate(boolean autoUpdate) {
        ValidatorContext.autoUpdate = autoUpdate;
    }

    public void setAutoUpdateSecond(int autoUpdateSecond) {
        ValidatorContext.autoUpdateSecond = autoUpdateSecond;
    }

}
